package com.chenjun.core.service.oa.impl;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chenjun.common.Constant;
import com.chenjun.common.bean.Pagination;
import com.chenjun.common.model.DataGridModel;
import com.chenjun.common.model.DataGridSortModel;
import com.chenjun.core.dao.generator.entity.OaBillAttnDayReport;
import com.chenjun.core.dao.generator.entity.OaBillAttnMonthReport;
import com.chenjun.core.dao.generator.entity.OaBillAttnMonthReportDtl;
import com.chenjun.core.dao.generator.entity.OaBillLeaveApplication;
import com.chenjun.core.dao.generator.entity.OaDictYearCfg;
import com.chenjun.core.dao.generator.mapper.OaBillAttnMonthReportDtlMapper;
import com.chenjun.core.dao.generator.mapper.OaBillAttnMonthReportMapper;
import com.chenjun.core.dao.generator.mapper.OaDictYearCfgMapper;
import com.chenjun.core.dao.module.OaBillAttnDayReportRelationMapper;
import com.chenjun.core.dao.module.OaBillAttnMonthReportDtlRelationMapper;
import com.chenjun.core.dao.module.OaBillAttnMonthReportRelationMapper;
import com.chenjun.core.dao.module.OaBillLeaveApplicationRelationMapper;
import com.chenjun.core.service.oa.OaBillAttnMonthReportService;
import com.chenjun.core.vo.activiti.MonthReportStatisticsDto;
import com.chenjun.core.vo.activiti.TravelStatistcsDto;
import com.chenjun.core.vo.activiti.YearReportStatisticsDto;

/**
 * @Description: 月结数据
 * @author dongyibin
 * @date 2017-9-3 下午2:35:30
 */
@Service
@Transactional
@SuppressWarnings("serial")
public class OaBillAttnMonthReportServierImpl implements OaBillAttnMonthReportService {
	private Logger logger = Logger.getLogger(OaBillAttnMonthReportServierImpl.class);
	@Autowired
	private OaBillAttnDayReportRelationMapper dayReportRelationMapper;
	@Autowired
	private OaBillAttnMonthReportMapper monthReportMapper;
	@Autowired
	private OaBillAttnMonthReportRelationMapper monthReportRelationMapper;
	@Autowired
	private OaBillAttnMonthReportDtlMapper monthReportDtlMapper;
	@Autowired
	private OaBillAttnMonthReportDtlRelationMapper monthReportDtlRelationMapper;
	@Autowired
	private OaBillLeaveApplicationRelationMapper leaveApplicationRelationMapper;
	@Autowired
	private OaDictYearCfgMapper yearCfgMapper;
	

	@Override
	public OaBillAttnMonthReport get(int id) {
		return monthReportMapper.selectByPrimaryKey(id);
	}

	@Override
	public int create(OaBillAttnMonthReport oaBillAttnMonthReport) {
		return monthReportMapper.insert(oaBillAttnMonthReport);
	}

	@Override
	public int delete(int id) {
		return monthReportMapper.deleteByPrimaryKey(id);
	}

	@Override
	public int update(OaBillAttnMonthReport oaBillAttnMonthReport) {
		return monthReportMapper.updateByPrimaryKeySelective(oaBillAttnMonthReport);
	}

	@Override
	public int createOrUpdate(OaBillAttnMonthReport oaBillAttnMonthReport) {
		int rows = 0;
		if (StringUtils.isBlank(oaBillAttnMonthReport.getId().toString())) {
			rows = create(oaBillAttnMonthReport);
		} else {
			rows = update(oaBillAttnMonthReport);
		}
		return rows;
	}

	@Override
	public List<OaBillAttnMonthReport> doListByCondition(DataGridModel param) {
		return monthReportRelationMapper.selectByCondition(param);
	}

	/**
	 * Description: 月报统计
	 * 
	 * @param model
	 * @return
	 * @throws Exception 
	 */
	@Override
	public Pagination getMonthReport(DataGridModel model) throws Exception {
		// 取用户、日期遍历得到所有的日报
		// 取日期月报明细
		// dto封装数据
		Pagination vo = new Pagination();
		boolean tag = false;
		Calendar currDate = Calendar.getInstance();
		currDate.setTime(new Date());
		int year = currDate.get(Calendar.YEAR);
		int month = currDate.get(Calendar.MONTH) + 1;
		String userids = model.getParams().get("userIds").toString();
		String date = model.getParams().get("startTime").toString();
		if(!(StringUtils.isBlank(date) || date.equals("null"))){
			String[] dates = date.split("-");
			int y = Integer.parseInt(dates[0]);
			int m = Integer.parseInt(dates[1]);
			if(year==y && month<=m){ // 不能取当月数据
				tag = false;
			}else{
				tag = true;
				year = y;
				month = m;
			}
		}
		List<MonthReportStatisticsDto> results = new ArrayList<>();
		if(tag){
			String[] ids = userids.replaceAll("'", "").split(",");// js处理中加了单引号
			for (String userid : ids) {
				if(StringUtils.isBlank(userid)){
					continue;
				}
				DataGridModel param = new DataGridModel();
				param.setRows(0);
				param.getParams().put("year", year);
				param.getParams().put("month", month);
				param.getParams().put("emplId", userid);
				param.getParams().put("status", Constant.STATUS_TRUE);
				param.getSortBy().add(new DataGridSortModel("bill_date", DataGridSortModel.ASC));
				MonthReportStatisticsDto dto = new MonthReportStatisticsDto(); // 月报统计数据
				// 出勤统计
				BigDecimal all_attendanceHours = new BigDecimal(0f); // 出勤小时数
				List<OaBillAttnDayReport> dayReports = dayReportRelationMapper.selectByCondition(param);
				Integer all_attendanceDays = 0; // 出勤天数
				for(OaBillAttnDayReport dayReport : dayReports){ // 这个月所有日报
					Calendar c = Calendar.getInstance();
					c.setTime(dayReport.getBillDate());
					Integer day = c.get(Calendar.DAY_OF_MONTH);
					Float normalHours = dayReport.getNormalHours(); // 工作小时数
					all_attendanceDays++;
					all_attendanceHours = all_attendanceHours.add(new BigDecimal(normalHours));
					// 赋值
					Method method = dto.getClass().getMethod("setDay_" + day, new Class[]{String.class});
					method.invoke(dto, dayReport.getNormalHours().toString());
					dto.setEmplId(dayReport.getEmplId());
				}
				// 请假统计
				Integer vacation_nuptialOrFuneral = 0; // 喜丧假
				Integer vacation_sick = 0; // 病假
				Integer vacation_affair = 0; // 事假
				Integer vacation_year = 0; // 年休假
				List<OaBillLeaveApplication> leaveApplications = leaveApplicationRelationMapper.selectByCondition(param);
				for(OaBillLeaveApplication leaveApplication : leaveApplications){
					leaveApplication.getLeaveBeginTime();
					leaveApplication.getLeaveEndTime();
					Integer leaveTypeId = leaveApplication.getLeaveTypeId();
					switch (leaveTypeId) {
					case 1: // 喜丧假
						vacation_nuptialOrFuneral++;
						break;
					case 2: // 病假
						vacation_sick++;
						break;
					case 3: // 事假
						vacation_affair++;
						break;
					case 4: // 年休假
						vacation_year++;
						break;
					default:
						break;
					}
				}
				// 加班统计
				dto.setEmplName(userid);
				dto.setVacation_sick(vacation_sick.toString());
				dto.setVacation_year(vacation_year.toString());
				dto.setVacation_affair(vacation_affair.toString());
				dto.setAttendanceDays(all_attendanceDays.toString());
				dto.setVacation_nuptialOrFuneral(vacation_nuptialOrFuneral.toString());
				dto.setAttendanceHours(((Float)all_attendanceHours.floatValue()).toString());
				results.add(dto);
			}
		}
		vo.setAaData(results);
		vo.setiTotalRecords(results.size());
		vo.setsEcho(model.getPage());
		vo.setiTotalDisplayRecords(results.size());
		return vo;
	}

	/**
	 * 从月报中取出勤数据
	 */
	@Override
	public Pagination getAttnDetailStatistics(DataGridModel dataGridModel) {
		Pagination vo = new Pagination();
		// 默认取当月数据
		Calendar currDate = Calendar.getInstance();
		currDate.setTime(new Date());
		int year = currDate.get(Calendar.YEAR);
		int month = currDate.get(Calendar.MONTH) + 1;
		String userids = dataGridModel.getParams().get("userIds").toString();
		String date = dataGridModel.getParams().get("startTime").toString();
		if(!(StringUtils.isBlank(date) || date.equals("null"))){
			String[] dates = date.split("-");
			year = Integer.parseInt(dates[0]);
			month = Integer.parseInt(dates[1]);
		}
		List<TravelStatistcsDto> results = new ArrayList<>();
		String[] ids = userids.replaceAll("'", "").split(",");// js处理中加了单引号
		for (String userid : ids) {
			if(StringUtils.isBlank(userid)){
				continue;
			}
			BigDecimal zero = new BigDecimal(0f);
			// 不同日期加班小时数
			BigDecimal thisTravelHours = new BigDecimal(0f);
			BigDecimal thisRealTravelHours = new BigDecimal(0f);
			BigDecimal thisDiffTravelHours = new BigDecimal(0f);
			
			BigDecimal allTravelHours = new BigDecimal(0f);
			BigDecimal allRealTravelHours = new BigDecimal(0f);
			BigDecimal allDiffTravelHours = new BigDecimal(0f);
			TravelStatistcsDto dto = new TravelStatistcsDto();
			dto.setStatisticsDate(year + "年" + month + "月");
			int minMonth = 1; // 年度最小月份
			boolean tag = true;
			Map<String, BigDecimal> p = new HashMap<>();
			while(month>= minMonth){
				p.put("travelHours", zero);
				p.put("realTravelHours", zero);
				p.put("diffTravelHours", zero);
				BigDecimal travelHours = new BigDecimal(0f);
				BigDecimal realTravelHours = new BigDecimal(0f);
				BigDecimal diffTravelHours = new BigDecimal(0f);
				getMonthAttenDetailStatistics(year,month,userid,p);
				travelHours = p.get("travelHours");
				realTravelHours = p.get("realTravelHours");
				diffTravelHours = p.get("diffTravelHours");
				if(tag){
					tag = false;
					thisTravelHours = travelHours;
					thisRealTravelHours = realTravelHours;
					thisDiffTravelHours = diffTravelHours;
				}
				allTravelHours = allTravelHours.add(travelHours);
				allRealTravelHours = allRealTravelHours.add(realTravelHours);
				allDiffTravelHours = allDiffTravelHours.add(diffTravelHours);
				month--;
			}
			dto.setEmplId(userid);
			DataGridModel param = new DataGridModel();
			param.setRows(0);
			param.getParams().put("emplId", userid);
			param.getSortBy().add(new DataGridSortModel("bill_date", DataGridSortModel.ASC));
			List<OaBillAttnMonthReport> oaBillAttnMonthReports = doListByCondition(param);
			if(oaBillAttnMonthReports != null && oaBillAttnMonthReports.size() > 0){
				OaBillAttnMonthReport report = oaBillAttnMonthReports.get(0);
				dto.setEmplName(report.getEmplName()); // 员工考勤方式设置表未实现
				dto.setHoursTypeName(report.getManHoursTypeName()); // 员工考勤方式设置表未实现
			}
			dto.setThis_travelHours(thisTravelHours.toString());
			dto.setThis_realTravelHours(thisRealTravelHours.toString());
			dto.setThis_diffTravelHours(thisDiffTravelHours.toString());
			dto.setAll_travelHours(allTravelHours.toString());
			dto.setAll_realTravelHours(allRealTravelHours.toString());
			dto.setAll_diffTravelHours(allDiffTravelHours.toString());
			results.add(dto);
		}
		vo.setAaData(results);
		vo.setiTotalRecords(results.size());
		vo.setsEcho(dataGridModel.getPage());
		vo.setiTotalDisplayRecords(results.size());
		return vo;
	}

	/**
	 * 月度考勤数据
	 * @Description: 
	 * @param year
	 * @param month
	 * @param userid
	 * @param p
	 * @author dongyibin
	 * @date 2017-10-18 下午9:25:42
	 */
	public void getMonthAttenDetailStatistics(int year, int month, String userid, Map<String, BigDecimal> p){
		BigDecimal travelHours = new BigDecimal(160f);
		BigDecimal realTravelHours = new BigDecimal(0f);
		BigDecimal diffTravelHours = new BigDecimal(0f);
		// 查询当月包含的出勤信息
		DataGridModel param = new DataGridModel();
		param.setRows(0);
		param.getParams().put("year", year);
		param.getParams().put("month", month);
		param.getParams().put("emplId", userid);
		param.getSortBy().add(new DataGridSortModel("bill_date", DataGridSortModel.ASC));
		List<OaBillAttnMonthReport> oaBillAttnMonthReports = doListByCondition(param);
		if (oaBillAttnMonthReports == null || oaBillAttnMonthReports.isEmpty()) {
			return;
		}
		// 此月月报，只有一条数据
		for (OaBillAttnMonthReport oaBillAttnMonthReport : oaBillAttnMonthReports) {
			DataGridModel model = new DataGridModel();
			param.setRows(0);
			param.getParams().put("billId", oaBillAttnMonthReport.getId());
			param.getParams().put("reportKey", Constant.MONTHREPORT_ATTENDANCE_HOURS); // 出勤小时
			List<OaBillAttnMonthReportDtl> monthReportDtls = monthReportDtlRelationMapper.selectByCondition(model);
			for(OaBillAttnMonthReportDtl monthReportDtl : monthReportDtls){ // 取这个月的出勤小时数
				Float reportVal = monthReportDtl.getReportVal();
				realTravelHours.add(new BigDecimal(reportVal));
			}
			diffTravelHours = diffTravelHours.add(travelHours.subtract(realTravelHours));
			p.put("travelHours", travelHours);
			p.put("realTravelHours", realTravelHours);
			p.put("diffTravelHours", diffTravelHours);
		}
	}
	
	/**
	 * 年报数据
	 * @Description: 员工部门、年需出勤时长、出勤日期 系统中没找到，带修正
	 * @author dongyibin
	 * @date 2017-10-18 下午9:25:42
	 */
	@Override
	public Pagination getYearReport(DataGridModel model) {
		// 根据用户id、年份，取公司年度设置时间，得到此年所有月份，取这些月报明细
		Pagination vo = new Pagination();
		String userids = model.getParams().get("userIds").toString();
		String date = model.getParams().get("startTime").toString();
		int year = Calendar.getInstance().get(Calendar.YEAR);
		if(!(StringUtils.isBlank(date) || date.equals("null"))){
			year = Integer.parseInt(date);
		}
		
		// 取系统设置的年度
		Date startTime = null, endTime = null;
		DataGridModel param = new DataGridModel();
		param.setRows(0);
		param.getParams().put("name", year);
		param.getParams().put("status", Constant.STATUS_TRUE);
		List<OaDictYearCfg> yearCfg = yearCfgMapper.selectByCondition(param);
		if(yearCfg != null && yearCfg.size() > 0){
			OaDictYearCfg oaDictYearCfg = yearCfg.get(0);
			startTime = oaDictYearCfg.getYearBeginDate();
			endTime = oaDictYearCfg.getYearEndDate();
		}
		if(startTime == null || endTime == null){ // 未设置年度
			logger.error("当前系统未设置年度");
			return vo;
		}
		
		List<YearReportStatisticsDto> data = new ArrayList<>();
		// 取用户年度的月报
		String[] ids = userids.replaceAll("'", "").split(",");// js处理中加了单引号
		for (String userid : ids) {
			if (StringUtils.isBlank(userid)) {
				continue;
			}
			param = new DataGridModel();
			param.setRows(0);
			param.getParams().put("emplId", userid);
			param.getParams().put("startTime", startTime);
			param.getParams().put("endTime", endTime);
			param.getSortBy().add(new DataGridSortModel("bill_date", DataGridSortModel.ASC));
			data.add(getYearReportDetail(userid, param));
			
		}
		vo.setAaData(data);
		vo.setiTotalRecords(data.size());
		vo.setsEcho(model.getPage());
		vo.setiTotalDisplayRecords(data.size());
		return vo;
	}
	
	/**
	 * @Description: 取月报明细
	 * @return
	 * @author dongyibin
	 * @param param 
	 * @date 2017-11-11 下午8:36:07
	 */
	public YearReportStatisticsDto getYearReportDetail(String userid, DataGridModel param){
		// 取这年的所有月报
		List<OaBillAttnMonthReport> monthReports = monthReportRelationMapper.selectByCondition(param);
		// dto属性定义
		String emplName = "-", emplCode = "-", hoursTypeName = "-", groupName = "-";
		float absentHours = 0f;// 旷工时长
		int attDays = 0;// 出勤天数
		BigDecimal shouldAttHours = new BigDecimal(0f);;// 应出勤小时数
		BigDecimal attHours = new BigDecimal(0f);// 出勤小时
		BigDecimal averageDayHours = new BigDecimal(0f);// 日平均工时
		BigDecimal overTimeHours = new BigDecimal(0f);// 加班时长
		BigDecimal holidayOvertimeHours = new BigDecimal(0f);// 法定节假日加班时长
		BigDecimal riteLeaveHours = new BigDecimal(0f); // 喜丧假
		BigDecimal sickLeaveHours = new BigDecimal(0f); // 病假
		BigDecimal affairsLeaveHours = new BigDecimal(0f); // 事假
		BigDecimal yearLeaveHours = new BigDecimal(0f); // 年休假
		BigDecimal paidLeaveHours = new BigDecimal(0f); // 调休
		BigDecimal inductrialInjuryHours = new BigDecimal(0f); // 工伤
		for(OaBillAttnMonthReport report : monthReports){
			int reportId = report.getId();
			emplName = report.getEmplName();
			emplCode = report.getEmplCode();
			hoursTypeName = report.getManHoursTypeName();
			
			// 取月报明细
			param = new DataGridModel();
			param.setRows(0);
			param.getParams().put("bill_id", reportId);
			List<OaBillAttnMonthReportDtl> repotDetails = monthReportDtlRelationMapper.selectByCondition(param);
			for(OaBillAttnMonthReportDtl reportDetail: repotDetails){
				BigDecimal reportVal = new BigDecimal(reportDetail.getReportVal());
				switch (reportDetail.getReportKey()) {
				case "bj": // 病假
					sickLeaveHours = sickLeaveHours.add(reportVal);
					break;
				case "sj": // 事假
					affairsLeaveHours = affairsLeaveHours.add(reportVal);
					break;
				case "gs": // 工伤
					inductrialInjuryHours = inductrialInjuryHours.add(reportVal);
					break;
				case "xsj": // 喜丧假
					riteLeaveHours = riteLeaveHours.add(reportVal);
					break;
				case "nxj": // 年休假
					yearLeaveHours = yearLeaveHours.add(reportVal);
					break;
				case "tx": // 调休
					paidLeaveHours = paidLeaveHours.add(reportVal);
					break;
				case Constant.MONTHREPORT_ATTENDANCE_HOURS: // 出勤小时
					attHours = attHours.add(reportVal);
					break;
				case Constant.MONTHREPORT_ATTENDANCE_DAYS: // 出勤天数
					attDays += reportVal.intValue();
					break;
				case Constant.MONTHREPORT_OVERTIME_HOURS: // 加班时长
					overTimeHours = overTimeHours.add(reportVal);
					break;
				case Constant.MONTHREPORT_HOLIDAYOVERTIME_HOURS: // 法定节假日加班时长
					holidayOvertimeHours = holidayOvertimeHours.add(reportVal);
					break;
				default:
					logger.error("请假类型异常，出现未能捕获的类型: "+ reportDetail.getReportKey());
					break;
				}
			}
			
		}
		if(shouldAttHours.compareTo(attHours) == 1){ // 有旷工情况
			absentHours = shouldAttHours.subtract(attHours).floatValue();
		}
		YearReportStatisticsDto yearReport = new YearReportStatisticsDto();
		yearReport.setEmplId(userid);
		yearReport.setEmplName(emplName);
		yearReport.setEmplCode(emplCode);
		yearReport.setHoursTypeName(hoursTypeName);
		yearReport.setAbsentHours(absentHours);// 旷工时长
		yearReport.setAttDays(attDays);// 出勤天数
		yearReport.setAttHours(attHours.floatValue());// 出勤小时
		yearReport.setShouldAttHours(shouldAttHours.floatValue());// 应出勤小时数
		yearReport.setAverageDayHours(averageDayHours.floatValue());// 日平均工时
		yearReport.setOverTimeHours(overTimeHours.floatValue());// 加班时长
		yearReport.setHolidayOvertimeHours(holidayOvertimeHours.floatValue());// 法定节假日加班时长
		yearReport.setRiteLeaveHours(riteLeaveHours.floatValue());// 喜丧假
		yearReport.setAffairsLeaveHours(affairsLeaveHours.floatValue());// 事假
		yearReport.setSickLeaveHours(sickLeaveHours.floatValue());// 病假
		yearReport.setYearLeaveHours(yearLeaveHours.floatValue());// 年休假
		yearReport.setPaidLeaveHours(paidLeaveHours.floatValue());// 调休
		yearReport.setInductrialInjuryHours(inductrialInjuryHours.floatValue()); // 工伤
		return yearReport;
		
	}
	
}
